/**
 * Copyright 2016-2018 mobaas.com
 */
package com.mobaas.devops.monitor;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.mobaas.devops.HostMonitor;
import com.mobaas.devops.model.HostStat;
import com.mobaas.devops.util.CryptoUtils;

/**
 * SSH方式主机监控
 * @author billy zhang
 *
 */
public class SshHostMonitor implements HostMonitor {

	@Override
	public List<HostStat> getHostStat(Map<String, Object> config) {
		
		String host = (String)config.get("host");
		String encPasswd = (String)config.get("password");
		String secretKey = (String)config.get("secretKey");
		
		HostStat hs = new HostStat();
		
		String password = CryptoUtils.decryptDES(encPasswd, secretKey.substring(0, 8));
		
		JSch jsch = new JSch();
		   
        try {
	        	Session sess = jsch.getSession("root", host);
	        	sess.setPassword(password);
	        	 Properties properties = new Properties();  
             properties.put("StrictHostKeyChecking", "no");  
             sess.setConfig(properties);  
	        	sess.connect();
	        	
	        	Channel channel = sess.openChannel("sftp");
	        	channel.connect();
	        	
	        	ChannelSftp sftp = (ChannelSftp)channel;
	        	
	        	try {
                //long startTime = System.currentTimeMillis();  
                //byte[] netinfo1 = getContent( sftp.open("/proc/net/dev") );
                byte[] stat1 = getContent(sftp.get("/proc/stat") );
                
                
                Thread.sleep(2000);

                //long endTime = System.currentTimeMillis();  
                //byte[] netinfo2 = getContent( sftp.open("/proc/net/dev") );
                byte[] stat2 = getContent( sftp.get("/proc/stat") );

                hs.setCPU(calculateCpuUsed(stat1, stat2));
                fillMemInfo(hs, getContent(sftp.get("/proc/meminfo")) );
                
                //fillNetInfo(hs, netinfo1, netinfo2, (int)(endTime-startTime));
                
            } finally {
                sftp.disconnect();;
            }
            
        		sess.disconnect();
        } catch (Exception ex) {
        		ex.printStackTrace();
        }
	    
        List<HostStat> list = new ArrayList<>();
        list.add(hs);
        
		return list;
	}

	private byte[] getContent(InputStream inStream) throws IOException {
		byte[] buf = new byte[65536];
    		ByteArrayOutputStream baos = new ByteArrayOutputStream();
    	
        int len = 0;
        while ((len = inStream.read(buf, 0, buf.length)) > 0) {
        		baos.write(buf, 0, len);
        }
        
        inStream.close();
        
        return baos.toByteArray();
	}
	
	public static float calculateCpuUsed(byte[] stat1, byte[] stat2) throws IOException {
		 BufferedReader br = new BufferedReader(new InputStreamReader(
			        new ByteArrayInputStream(stat1)));
	    StringTokenizer token = new StringTokenizer(br.readLine());
	    token.nextToken();
	    int user1 = Integer.parseInt(token.nextToken());
	    int nice1 = Integer.parseInt(token.nextToken());
	    int sys1 = Integer.parseInt(token.nextToken());
	    int idle1 = Integer.parseInt(token.nextToken());
	    br.close();
	    
	    br = new BufferedReader(new InputStreamReader(
		        new ByteArrayInputStream(stat2)));
	    token = new StringTokenizer(br.readLine());
	    token.nextToken();
	    int user2 = Integer.parseInt(token.nextToken());
	    int nice2 = Integer.parseInt(token.nextToken());
	    int sys2 = Integer.parseInt(token.nextToken());
	    int idle2 = Integer.parseInt(token.nextToken());
	    br.close();
	    
	    return 100.0f * ( (user2 + sys2 + nice2) - (user1 + sys1 + nice1)) /
	            ( (user2 + nice2 + sys2 + idle2) - (user1 + nice1 + sys1 + idle1));
	}
	
	public static void fillMemInfo(HostStat stat, byte[] data) 
			throws IOException, InterruptedException {

	    BufferedReader br = new BufferedReader(new InputStreamReader(
	        new ByteArrayInputStream(data)));

	      int memTotal = 0;
	      int memFree = 0;
	      int swapTotal = 0;
	      int swapFree = 0;
	      
	    String str = null;
	    StringTokenizer token = null;
	    while ( (str = br.readLine()) != null) {
	      token = new StringTokenizer(str);
	      if (!token.hasMoreTokens()) {
	        continue;
	      }

	      str = token.nextToken();
	      if (!token.hasMoreTokens()) {
	        continue;
	      }
	      
	      if (str.equalsIgnoreCase("MemTotal:")) {
	        memTotal = Integer.parseInt(token.nextToken());
	      }
	      else if (str.equalsIgnoreCase("MemFree:")) {
	        memFree = Integer.parseInt(token.nextToken());
	      }
	      else if (str.equalsIgnoreCase("SwapTotal:")) {
	        swapTotal = Integer.parseInt(token.nextToken());
	      }
	      else if (str.equalsIgnoreCase("SwapFree:")) {
	        swapFree = Integer.parseInt(token.nextToken());
	      }
	      
	    }
	    
	    br.close();

	      stat.setMemTotal(memTotal);
	      stat.setMemUsage(memTotal - memFree - (swapTotal - swapFree));
	  }
	
	public static void fillNetInfo(HostStat stat, byte[] data1, byte[] data2, int interval) 
			throws IOException, InterruptedException {
	
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new ByteArrayInputStream(data1)));  
        String line = null;  
        long inSize1 = 0, outSize1 = 0;  
        while((line=br.readLine()) != null){     
            line = line.trim();  
            if(line.startsWith("eth0")){   
                String[] temp = line.split("\\s+");   
                inSize1 = Long.parseLong(temp[0].substring(5)); //Receive bytes,单位为Byte  
                outSize1 = Long.parseLong(temp[8]);             //Transmit bytes,单位为Byte  
                break;  
            }                 
        }     
        br.close();  
        
        br = new BufferedReader(new InputStreamReader(
				new ByteArrayInputStream(data2)));  
        line = null;  
        long inSize2 = 0, outSize2 = 0;  
        while((line=br.readLine()) != null){     
            line = line.trim();  
            if(line.startsWith("eth0")){   
                String[] temp = line.split("\\s+");   
                inSize2 = Long.parseLong(temp[0].substring(5)); //Receive bytes,单位为Byte  
                outSize2 = Long.parseLong(temp[8]);             //Transmit bytes,单位为Byte  
                break;  
            }                 
        }     
        br.close();  
        
        if(inSize1 != 0 && outSize1 !=0 && inSize2 != 0 && outSize2 !=0){  
            //网口传输速度,单位为bps  
            stat.setNetRx( (int)Math.ceil((float)(inSize2 - inSize1)*8/(1000*interval)) );  
            stat.setNetTx( (int)Math.ceil((float)(outSize2 - outSize1)*8/(1000*interval)) ); 
           
        }     
	}


}
